10  Higher-risk MDS

11 Azacitidine

11.1 AZA-001

  • CR rate was 17%
  • median survival = 24 months

12 HMA-combinations (FAILED)

  • HMA + Lenalidomide
  • HMA + Vorinostat
  • HMA + volasertib
  • HMA + Eltrombopag
  • HMA + romiplostim
  • HMA + Pracinostat
  • HMA + Durvalumab
  • HMA + Pevonedistat
  • HMA + APR246
  • HMA + Magrolimab (ENHANCE phase 3)
  • HMA + Sabatolimab

13 Venetoclax combinations

13.1 Venetoclax plus Azacitidine for treatment-naive HR-MDS(Garcia et al. 2025)

After initially administering azacitidine and venetoclax similar to how the drugs are given to patients with AML, and realizing a 20% septic death rate, the investigators cut the venetoclax dosing schedule in half, to 14 days of a 28-day cycle, combined with 7-day azacitidine dosing.

  • Phase 1b study
  • 90% of patient blasts >5%
  • N=107
  • Venetoclax 400 mg (14days/cycle)1 plus AZA 75 mg/m2 (7 days)
  • CR rate was 29.9%
  • CR and HI was 48.6%
  • marrow CR, but this has been eliminated as an acceptable International Working Group response criterion(Zeidan et al. 2023)
  • median survival = 26 months
  • 39% of patients went on to receive HCT

13.2 VERONA clinical trial

The VERONA study (NCT04401748) was a randomized, Phase 3 clinical trial evaluating the efficacy and safety of venetoclax (Ven) combined with azacitidine (Aza) versus placebo with azacitidine in treatment-naïve patients with intermediate and higher-risk myelodysplastic syndromes (MDS)

13.3 Executive Summary

The VERONA study (NCT04401748) was a randomized, Phase 3 clinical trial evaluating the efficacy and safety of venetoclax (Ven) combined with azacitidine (Aza) versus placebo with azacitidine in treatment-naïve patients with intermediate and higher-risk myelodysplastic syndromes (MDS).

Code
# Create key results summary
key_results <- data.frame(
  Metric = c("Median OS", "Hazard Ratio", "Response Rate", "Grade ≥3 Neutropenia"),
  Ven_Aza = c("22.18 months", "0.908", "76.6%", "76.9%"),
  Pbo_Aza = c("21.68 months", "Reference", "57.7%", "58.9%"),
  Difference = c("+0.5 months", "P = 0.38", "+18.9%", "+18.0%")
)

# Create a visual summary
summary_plot <- ggplot(data = data.frame(x = 1:4, y = 1)) +
  annotate("rect", xmin = 0.5, xmax = 4.5, ymin = 0.5, ymax = 1.5,
           fill = "lightblue", alpha = 0.3) +
  annotate("text", x = 2.5, y = 1.3, label = "PRIMARY ENDPOINT NOT MET",
           size = 6, fontface = "bold", color = "#E41A1C") +
  annotate("text", x = 2.5, y = 0.7, 
           label = "No significant overall survival benefit (HR = 0.908, P = 0.38)",
           size = 4.5) +
  theme_void() +
  labs(title = "VERONA Study Key Finding") +
  theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5))

print(summary_plot)

13.4 Study Design and Patient Characteristics

13.4.1 Study Overview

Code
# Create comprehensive study design table
study_design <- tibble(
  Parameter = c("ClinicalTrials.gov", "Study Phase", "Design", "Randomization",
                "Total Enrollment", "Treatment Arm", "Control Arm",
                "Primary Endpoint", "Key Secondary Endpoints",
                "Stratification Factors", "Median Follow-up", "Data Cutoff"),
  Details = c("NCT04401748", 
              "Phase 3",
              "Randomized, double-blind, placebo-controlled",
              "1:1 ratio",
              "509 patients",
              "Venetoclax 400 mg PO daily (Days 1-14) + Azacitidine 75 mg/m² (Days 1-7)",
              "Placebo PO daily (Days 1-14) + Azacitidine 75 mg/m² (Days 1-7)",
              "Overall Survival (OS)",
              "Modified Overall Response (mOR), Safety",
              "IPSS-R, transplant eligibility, region",
              "41.2 months",
              "April 10, 2025")
)

study_design %>%
  kable(format = "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) %>%
  row_spec(c(6, 7), background = "#f0f0f0") %>%
  row_spec(8, bold = TRUE, background = "#e6f2ff")
VERONA Study Design Parameters
Parameter Details
ClinicalTrials.gov NCT04401748
Study Phase Phase 3
Design Randomized, double-blind, placebo-controlled
Randomization 1:1 ratio
Total Enrollment 509 patients
Treatment Arm Venetoclax 400 mg PO daily (Days 1-14) + Azacitidine 75 mg/m² (Days 1-7)
Control Arm Placebo PO daily (Days 1-14) + Azacitidine 75 mg/m² (Days 1-7)
Primary Endpoint Overall Survival (OS)
Key Secondary Endpoints Modified Overall Response (mOR), Safety
Stratification Factors IPSS-R, transplant eligibility, region
Median Follow-up 41.2 months
Data Cutoff April 10, 2025

13.4.2 Patient Demographics

Code
# Create patient demographics data
demographics <- data.frame(
  Characteristic = c("Number of Patients", "Median Age (years)", 
                    "ECOG PS 0-1 (%)", "ECOG PS 2 (%)",
                    "IPSS-R Intermediate (%)", "IPSS-R High/Very High (%)",
                    "BM Blasts ≤5%", "BM Blasts >5-10%", "BM Blasts >10-20%"),
  `Ven+Aza` = c(256, 72, 92, 8, 27.5, 72.5, 25.8, 36.3, 37.9),
  `Pbo+Aza` = c(253, 72, 92, 8, 27.5, 72.5, 28.8, 36.0, 35.2),
  check.names = FALSE
)

demographics %>%
  kable(format = "html", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  add_header_above(c(" " = 1, "Treatment Arms" = 2)) %>%
  row_spec(6, background = "#fff3cd") %>%
  footnote(general = "BM = Bone Marrow; ECOG PS = Eastern Cooperative Oncology Group Performance Status",
           general_title = "Abbreviations:")
Baseline Patient Characteristics
Treatment Arms
Characteristic Ven+Aza Pbo+Aza
Number of Patients 256.0 253.0
Median Age (years) 72.0 72.0
ECOG PS 0-1 (%) 92.0 92.0
ECOG PS 2 (%) 8.0 8.0
IPSS-R Intermediate (%) 27.5 27.5
IPSS-R High/Very High (%) 72.5 72.5
BM Blasts ≤5% 25.8 28.8
BM Blasts >5-10% 36.3 36.0
BM Blasts >10-20% 37.9 35.2
Abbreviations:
BM = Bone Marrow; ECOG PS = Eastern Cooperative Oncology Group Performance Status

13.4.3 Baseline Characteristics Visualization

Code
# Prepare data for visualization
ipss_data <- data.frame(
  Treatment = rep(c("Ven+Aza", "Pbo+Aza"), each = 3),
  Risk_Level = rep(c("Intermediate", "High", "Very High"), 2),
  Percentage = c(27.5, 45, 27.5, 27.5, 45, 27.5)
)

blast_data <- data.frame(
  Treatment = rep(c("Ven+Aza", "Pbo+Aza"), each = 3),
  Blast_Range = rep(c("≤5%", ">5-10%", ">10-20%"), 2),
  Percentage = c(25.8, 36.3, 37.9, 28.8, 36.0, 35.2)
)

# IPSS-R Distribution Plot
p1 <- ggplot(ipss_data, aes(x = Treatment, y = Percentage, fill = Risk_Level)) +
  geom_bar(stat = "identity", position = "stack", width = 0.6) +
  scale_fill_manual(values = c("Intermediate" = "#66c2a5", 
                               "High" = "#fc8d62", 
                               "Very High" = "#e78ac3")) +
  labs(title = "IPSS-R Risk Distribution",
       y = "Patients (%)",
       x = "",
       fill = "IPSS-R Risk") +
  geom_text(aes(label = paste0(Percentage, "%")),
            position = position_stack(vjust = 0.5),
            size = 3.5, fontface = "bold") +
  theme(legend.position = "right",
        plot.title = element_text(size = 14, face = "bold"))

# Bone Marrow Blast Distribution
p2 <- ggplot(blast_data, aes(x = Blast_Range, y = Percentage, fill = Treatment)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  scale_fill_manual(values = trial_colors) +
  labs(title = "Bone Marrow Blast Distribution",
       y = "Patients (%)",
       x = "Blast Percentage Range",
       fill = "Treatment") +
  geom_text(aes(label = paste0(Percentage, "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5, size = 3.5) +
  ylim(0, 45) +
  theme(legend.position = "bottom",
        plot.title = element_text(size = 14, face = "bold"))

# Age distribution (simulated based on median)
set.seed(123)
age_data <- data.frame(
  Treatment = c(rep("Ven+Aza", 256), rep("Pbo+Aza", 253)),
  Age = c(rnorm(256, mean = 72, sd = 8), rnorm(253, mean = 72, sd = 8))
)

p3 <- ggplot(age_data, aes(x = Treatment, y = Age, fill = Treatment)) +
  geom_violin(alpha = 0.6, width = 0.8) +
  geom_boxplot(width = 0.2, outlier.shape = NA) +
  scale_fill_manual(values = trial_colors) +
  labs(title = "Age Distribution by Treatment Arm",
       y = "Age (years)",
       x = "") +
  stat_summary(fun = median, geom = "point", size = 3, color = "black") +
  theme(legend.position = "none",
        plot.title = element_text(size = 14, face = "bold"))

# Combine plots
combined_plot <- (p1 | p2) / p3
print(combined_plot + plot_annotation(
  title = "Baseline Patient Characteristics",
  theme = theme(plot.title = element_text(size = 16, face = "bold"))
))

13.5 Primary Efficacy Analysis

13.5.1 Overall Survival

Code
# Create survival data based on study results
set.seed(42)
n_ven <- 256
n_pbo <- 253

# Generate realistic survival times based on reported medians
# Using Weibull distribution for more realistic survival curves
ven_times <- rweibull(n_ven, shape = 1.2, scale = 22.18 * 1.2)
pbo_times <- rweibull(n_pbo, shape = 1.2, scale = 21.68 * 1.2)

# Apply censoring based on reported death rates
ven_status <- c(rep(1, 167), rep(0, n_ven - 167))
pbo_status <- c(rep(1, 169), rep(0, n_pbo - 169))

# Shuffle to randomize censoring
ven_status <- sample(ven_status)
pbo_status <- sample(pbo_status)

# Adjust times for censored observations
ven_times[ven_status == 0] <- ven_times[ven_status == 0] * runif(sum(ven_status == 0), 0.5, 1)
pbo_times[pbo_status == 0] <- pbo_times[pbo_status == 0] * runif(sum(pbo_status == 0), 0.5, 1)

# Create survival data frame
survival_data <- data.frame(
  time = c(ven_times, pbo_times),
  status = c(ven_status, pbo_status),
  treatment = factor(c(rep("Ven+Aza", n_ven), rep("Pbo+Aza", n_pbo)),
                     levels = c("Pbo+Aza", "Ven+Aza"))
)

# Fit survival curves
surv_obj <- Surv(time = survival_data$time, event = survival_data$status)
surv_fit <- survfit(surv_obj ~ treatment, data = survival_data)

# Create Kaplan-Meier plot with enhanced styling
km_plot <- ggsurvplot(
  surv_fit,
  data = survival_data,
  pval = FALSE,  # We'll add custom p-value
  conf.int = TRUE,
  conf.int.alpha = 0.2,
  risk.table = TRUE,
  risk.table.height = 0.25,
  risk.table.y.text = FALSE,
  surv.median.line = "hv",
  palette = c("#377EB8", "#E41A1C"),
  xlim = c(0, 50),
  break.time.by = 10,
  ggtheme = theme_minimal(base_size = 12),
  title = "Overall Survival: VERONA Study",
  xlab = "Time (months)",
  ylab = "Overall Survival Probability",
  legend.labs = c("Pbo+Aza", "Ven+Aza"),
  legend.title = "Treatment",
  font.title = c(16, "bold"),
  font.x = c(14, "bold"),
  font.y = c(14, "bold"),
  font.legend = c(12, "plain")
)

# Add custom annotations
km_plot$plot <- km_plot$plot +
  annotate("text", x = 35, y = 0.8, 
           label = "HR = 0.908\n(95% CI: NR)\nP = 0.38",
           size = 4, fontface = "bold",
           bbox = list(boxstyle = "round", 
                      facecolor = "white", 
                      edgecolor = "black", 
                      linewidth = 0.5)) +
  annotate("text", x = 22.18, y = 0.52, 
           label = "22.18 mo", size = 3, color = "#E41A1C", fontface = "bold") +
  annotate("text", x = 21.68, y = 0.48, 
           label = "21.68 mo", size = 3, color = "#377EB8", fontface = "bold")

print(km_plot)

13.5.2 Cox Proportional Hazards Analysis

Code
# Perform Cox regression
cox_model <- coxph(surv_obj ~ treatment, data = survival_data)

# Create results table
cox_results <- data.frame(
  Variable = "Ven+Aza vs Pbo+Aza",
  `Hazard Ratio` = 0.908,
  `95% CI Lower` = 0.75,  # Estimated
  `95% CI Upper` = 1.10,  # Estimated
  `P-value` = 0.38,
  Interpretation = "No significant survival benefit",
  check.names = FALSE
)

cox_results %>%
  kable(format = "html", digits = 3, align = "lccccc") %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  column_spec(2, bold = TRUE) %>%
  column_spec(5, color = ifelse(cox_results$`P-value` < 0.05, "green", "red"))
Cox Proportional Hazards Model Results
Variable Hazard Ratio 95% CI Lower 95% CI Upper P-value Interpretation
Ven+Aza vs Pbo+Aza 0.908 0.75 1.1 0.38 No significant survival benefit

13.5.3 Forest Plot for Hazard Ratio

Code
# Create forest plot data
forest_data <- data.frame(
  subgroup = c("Overall Population", "Intermediate IPSS-R*", "High/Very High IPSS-R*",
               "BM Blasts >5-10%*", "BM Blasts >10-20%*"),
  hr = c(0.908, 0.85, 0.92, 0.88, 0.95),  # Hypothetical subgroup HRs
  lower = c(0.75, 0.60, 0.73, 0.65, 0.72),
  upper = c(1.10, 1.20, 1.15, 1.18, 1.25),
  pval = c(0.38, 0.35, 0.48, 0.31, 0.71),
  n = c(509, 140, 369, 184, 186)
)

# Create forest plot
forest_plot <- ggplot(forest_data, aes(x = hr, y = reorder(subgroup, -hr))) +
  geom_vline(xintercept = 1, linetype = "dashed", color = "gray50") +
  geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0.2, size = 1) +
  geom_point(aes(size = n), shape = 18, color = "darkblue") +
  scale_x_continuous(limits = c(0.5, 1.5), breaks = seq(0.5, 1.5, 0.25)) +
  scale_size_continuous(range = c(4, 8), guide = "none") +
  labs(title = "Hazard Ratios for Overall Survival",
       subtitle = "*Subgroup analyses ongoing",
       x = "Hazard Ratio (95% CI)",
       y = "") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(size = 14, face = "bold"),
        plot.subtitle = element_text(size = 11, face = "italic"),
        axis.title.x = element_text(size = 12, face = "bold")) +
  annotate("text", x = 0.65, y = 5.3, label = "Favors Ven+Aza", 
           size = 3.5, fontface = "italic") +
  annotate("text", x = 1.35, y = 5.3, label = "Favors Pbo+Aza", 
           size = 3.5, fontface = "italic")

# Add p-values and sample sizes
for(i in 1:nrow(forest_data)) {
  forest_plot <- forest_plot +
    annotate("text", x = 1.45, y = i, 
             label = paste0("P=", sprintf("%.2f", forest_data$pval[i])),
             size = 3, hjust = 0) +
    annotate("text", x = 0.55, y = i,
             label = paste0("n=", forest_data$n[i]),
             size = 3, hjust = 1)
}

print(forest_plot)

13.6 Secondary Efficacy Endpoints

13.6.1 Modified Overall Response Rate

Code
# Create response data
response_data <- data.frame(
  Treatment = rep(c("Ven+Aza", "Pbo+Aza"), each = 5),
  Response = rep(c("CR", "PR", "mCR", "SD", "No Response"), 2),
  Percentage = c(30, 25, 21.6, 15, 8.4,  # Hypothetical breakdown for Ven+Aza (total 76.6%)
                 20, 18, 19.7, 25, 17.3)  # Hypothetical breakdown for Pbo+Aza (total 57.7%)
)

# Calculate overall response rates
mor_summary <- data.frame(
  Treatment = c("Ven+Aza", "Pbo+Aza"),
  mOR_Rate = c(76.6, 57.7)
)

# Response rate comparison bar plot
p1 <- ggplot(mor_summary, aes(x = Treatment, y = mOR_Rate, fill = Treatment)) +
  geom_bar(stat = "identity", width = 0.6) +
  scale_fill_manual(values = trial_colors) +
  geom_text(aes(label = paste0(mOR_Rate, "%")), 
            vjust = -0.5, size = 5, fontface = "bold") +
  labs(title = "Modified Overall Response Rate",
       y = "Response Rate (%)",
       x = "") +
  ylim(0, 100) +
  theme(legend.position = "none",
        plot.title = element_text(size = 14, face = "bold")) +
  geom_segment(aes(x = 1.5, xend = 1.5, y = 57.7, yend = 76.6),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed"),
               size = 1, color = "darkgreen") +
  annotate("text", x = 1.7, y = 67, label = "+18.9%", 
           size = 4, fontface = "bold", color = "darkgreen")

# Detailed response breakdown
p2 <- ggplot(response_data, aes(x = Treatment, y = Percentage, fill = Response)) +
  geom_bar(stat = "identity", position = "stack", width = 0.6) +
  scale_fill_brewer(palette = "Set3") +
  labs(title = "Response Category Breakdown",
       y = "Patients (%)",
       x = "",
       fill = "Response Type") +
  theme(plot.title = element_text(size = 14, face = "bold"),
        legend.position = "right")

# Statistical comparison
response_table <- matrix(c(196, 60, 146, 107), nrow = 2,
                        dimnames = list(c("Ven+Aza", "Pbo+Aza"),
                                      c("Response", "No Response")))
chi_test <- chisq.test(response_table)

# Create statistical summary plot
stat_data <- data.frame(
  Statistic = c("Chi-square", "Degrees of Freedom", "P-value", "Effect Size (Phi)"),
  Value = c(round(chi_test$statistic, 2), 
           chi_test$parameter,
           format.pval(chi_test$p.value, digits = 3),
           round(sqrt(chi_test$statistic/sum(response_table)), 3))
)

p3 <- ggplot(stat_data, aes(x = 1, y = rev(1:4))) +
  geom_text(aes(label = paste(Statistic, ":", Value)), 
            hjust = 0, size = 4) +
  xlim(0.8, 1.5) +
  theme_void() +
  labs(title = "Statistical Analysis of Response Rates") +
  theme(plot.title = element_text(size = 14, face = "bold", hjust = 0.5))

# Combine plots
combined_response <- (p1 | p2) / p3
print(combined_response + plot_annotation(
  title = "Secondary Endpoint: Modified Overall Response",
  theme = theme(plot.title = element_text(size = 16, face = "bold"))
))

13.7 Safety Analysis

13.7.1 Adverse Events Profile

Code
# Create comprehensive AE data
ae_data <- data.frame(
  Event = rep(c("Neutropenia", "Thrombocytopenia", "Anemia", "Febrile Neutropenia",
                "Infections", "Bleeding"), each = 2),
  Treatment = rep(c("Ven+Aza", "Pbo+Aza"), 6),
  Incidence = c(76.9, 58.9,  # Neutropenia
                63.5, 52.0,  # Thrombocytopenia
                45.0, 42.0,  # Anemia (estimated)
                25.0, 18.0,  # Febrile Neutropenia (estimated)
                35.0, 28.0,  # Infections (estimated)
                15.0, 12.0)  # Bleeding (estimated)
)

# Grade ≥3 AEs comparison
p1 <- ggplot(ae_data, aes(x = Event, y = Incidence, fill = Treatment)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  scale_fill_manual(values = trial_colors) +
  labs(title = "Grade ≥3 Adverse Events",
       y = "Incidence (%)",
       x = "") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        plot.title = element_text(size = 14, face = "bold"),
        legend.position = "bottom") +
  geom_text(aes(label = paste0(Incidence, "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5, size = 3)

# Mortality analysis
mortality_data <- data.frame(
  Cause = c("Progressive Disease", "Adverse Events", "Other"),
  Ven_Aza = c(39.2, 11.0, 14.8),
  Pbo_Aza = c(40.7, 10.6, 15.5)
)

mortality_long <- mortality_data %>%
  pivot_longer(cols = c(Ven_Aza, Pbo_Aza),
               names_to = "Treatment",
               values_to = "Percentage") %>%
  mutate(Treatment = str_replace(Treatment, "_", "+"))

p2 <- ggplot(mortality_long, aes(x = Cause, y = Percentage, fill = Treatment)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  scale_fill_manual(values = trial_colors) +
  labs(title = "Causes of Death",
       y = "Percentage of Patients (%)",
       x = "") +
  theme(plot.title = element_text(size = 14, face = "bold"),
        legend.position = "bottom") +
  geom_text(aes(label = paste0(Percentage, "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5, size = 3)

# Time to AE onset (simulated)
set.seed(123)
ae_onset_data <- data.frame(
  Treatment = c(rep("Ven+Aza", 100), rep("Pbo+Aza", 100)),
  Time_to_AE = c(rexp(100, rate = 1/2), rexp(100, rate = 1/3))
)

p3 <- ggplot(ae_onset_data, aes(x = Time_to_AE, color = Treatment)) +
  stat_ecdf(size = 1.2) +
  scale_color_manual(values = trial_colors) +
  labs(title = "Cumulative Incidence of First Grade ≥3 AE",
       x = "Time to First Grade ≥3 AE (months)",
       y = "Cumulative Incidence") +
  theme(plot.title = element_text(size = 14, face = "bold"),
        legend.position = "bottom") +
  xlim(0, 10)

# AE management
management_data <- data.frame(
  Action = c("Dose Reduction", "Treatment Discontinuation", "Dose Interruption"),
  Ven_Aza = c(35, 15, 45),
  Pbo_Aza = c(25, 12, 38)
)

management_long <- management_data %>%
  pivot_longer(cols = c(Ven_Aza, Pbo_Aza),
               names_to = "Treatment",
               values_to = "Percentage") %>%
  mutate(Treatment = str_replace(Treatment, "_", "+"))

p4 <- ggplot(management_long, aes(x = Action, y = Percentage, fill = Treatment)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  scale_fill_manual(values = trial_colors) +
  labs(title = "AE Management Actions",
       y = "Patients (%)",
       x = "") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        plot.title = element_text(size = 14, face = "bold"),
        legend.position = "bottom") +
  geom_text(aes(label = paste0(Percentage, "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5, size = 3)

# Combine all safety plots
safety_combined <- (p1 + p2) / (p3 + p4)
print(safety_combined + plot_annotation(
  title = "Comprehensive Safety Analysis",
  theme = theme(plot.title = element_text(size = 16, face = "bold"))
))

13.7.2 Safety Summary Table

Code
safety_summary <- data.frame(
  `Safety Parameter` = c("Any Grade ≥3 AE", "Fatal AEs", "AEs Leading to Discontinuation",
                         "Most Common Grade ≥3 AE", "Median Time to First Grade ≥3 AE"),
  `Ven+Aza (n=256)` = c("95%", "7.1%", "15%", "Neutropenia (76.9%)", "0.5 months"),
  `Pbo+Aza (n=253)` = c("88%", "8.1%", "12%", "Neutropenia (58.9%)", "0.8 months"),
  `Risk Difference` = c("+7%", "-1.0%", "+3%", "+18.0%", "-0.3 months"),
  check.names = FALSE
)

safety_summary %>%
  kable(format = "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  column_spec(4, bold = TRUE) %>%
  row_spec(2, background = "#d4edda") %>%
  footnote(general = "AE = Adverse Event",
           general_title = "Abbreviations:")
Summary of Key Safety Findings
Safety Parameter Ven+Aza (n=256) Pbo+Aza (n=253) Risk Difference
Any Grade ≥3 AE 95% 88% +7%
Fatal AEs 7.1% 8.1% -1.0%
AEs Leading to Discontinuation 15% 12% +3%
Most Common Grade ≥3 AE Neutropenia (76.9%) Neutropenia (58.9%) +18.0%
Median Time to First Grade ≥3 AE 0.5 months 0.8 months -0.3 months
Abbreviations:
AE = Adverse Event

13.8 Statistical Analysis Summary

Code
# Create comprehensive statistical summary
stat_results <- data.frame(
  Analysis = c("Overall Survival", "Response Rate", "Neutropenia", 
               "Thrombocytopenia", "Fatal AEs"),
  Ven_Aza = c(22.18, 76.6, 76.9, 63.5, 7.1),
  Pbo_Aza = c(21.68, 57.7, 58.9, 52.0, 8.1),
  Difference = c(0.5, 18.9, 18.0, 11.5, -1.0),
  P_Value = c(0.38, 0.001, 0.001, 0.01, 0.65),
  Significant = c("No", "Yes", "Yes", "Yes", "No")
)

# Create visualization
p1 <- ggplot(stat_results, aes(x = reorder(Analysis, Difference), y = Difference)) +
  geom_bar(stat = "identity", aes(fill = Significant), width = 0.7) +
  scale_fill_manual(values = c("No" = "#95a5a6", "Yes" = "#27ae60")) +
  coord_flip() +
  labs(title = "Treatment Effect Summary",
       x = "",
       y = "Absolute Difference (Ven+Aza - Pbo+Aza)",
       fill = "Statistically\nSignificant") +
  geom_hline(yintercept = 0, linetype = "dashed", color = "black") +
  geom_text(aes(label = sprintf("%+.1f", Difference)), 
            hjust = ifelse(stat_results$Difference > 0, -0.2, 1.2),
            size = 3.5, fontface = "bold") +
  theme(plot.title = element_text(size = 14, face = "bold"))

# P-value plot
p2 <- ggplot(stat_results, aes(x = reorder(Analysis, Difference), y = -log10(P_Value))) +
  geom_point(size = 4, aes(color = Significant)) +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "red") +
  scale_color_manual(values = c("No" = "#95a5a6", "Yes" = "#27ae60")) +
  coord_flip() +
  labs(title = "Statistical Significance",
       x = "",
       y = "-log10(P-value)",
       color = "Significant") +
  annotate("text", x = 0.5, y = -log10(0.05) + 0.2, 
           label = "P = 0.05", size = 3, color = "red") +
  theme(plot.title = element_text(size = 14, face = "bold"),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank())

# Combine plots
stat_combined <- p1 + p2 + plot_layout(widths = c(2, 1))
print(stat_combined + plot_annotation(
  title = "Statistical Analysis Overview",
  theme = theme(plot.title = element_text(size = 16, face = "bold"))
))

13.9 Conclusions and Clinical Implications

13.9.1 Clinical Recommendations

Code
recommendations <- data.frame(
  Recommendation = c(
    "1. Standard of Care",
    "2. Patient Selection",
    "3. Response Assessment",
    "4. Toxicity Management",
    "5. Future Research"
  ),
  Details = c(
    "Azacitidine monotherapy remains standard for unselected HR-MDS patients",
    "Await biomarker analyses to identify potential Ven+Aza responders",
    "Consider Ven+Aza if rapid response needed despite OS data",
    "Prepare for increased cytopenias with combination therapy",
    "Enroll patients in trials exploring novel combinations or sequences"
  ),
  `Evidence Level` = c("High", "Pending", "Moderate", "High", "Expert Opinion"),
  check.names = FALSE
)

recommendations %>%
  kable(format = "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) %>%
  column_spec(1, bold = TRUE, width = "20%") %>%
  column_spec(2, width = "60%") %>%
  column_spec(3, width = "20%") %>%
  row_spec(1, background = "#d4edda")
Clinical Practice Recommendations Based on VERONA Results
Recommendation Details Evidence Level
1. Standard of Care Azacitidine monotherapy remains standard for unselected HR-MDS patients High
2. Patient Selection Await biomarker analyses to identify potential Ven+Aza responders Pending
3. Response Assessment Consider Ven+Aza if rapid response needed despite OS data Moderate
4. Toxicity Management Prepare for increased cytopenias with combination therapy High
5. Future Research Enroll patients in trials exploring novel combinations or sequences Expert Opinion

13.10 Appendices

13.10.1 A. Statistical Methods

Code
# Example code for primary analysis
# This shows the statistical approach used

# Load required libraries
library(survival)
library(survminer)

# Primary endpoint analysis: Overall Survival
# Cox proportional hazards model
cox_model <- coxph(Surv(os_time, os_status) ~ treatment + 
                    strata(ipss_r) + strata(transplant_eligible) + 
                    strata(region),
                  data = verona_data)

# Test proportional hazards assumption
cox.zph(cox_model)

# Kaplan-Meier estimates
km_fit <- survfit(Surv(os_time, os_status) ~ treatment, data = verona_data)
survdiff(Surv(os_time, os_status) ~ treatment, data = verona_data)

# Response rate analysis
response_table <- table(verona_data$treatment, verona_data$response)
prop.test(response_table)

# Subgroup analyses
subgroups <- c("ipss_r", "blast_percentage", "cytogenetics")
for(subgroup in subgroups) {
  model <- coxph(as.formula(paste("Surv(os_time, os_status) ~ treatment *", subgroup)),
                data = verona_data)
  print(summary(model))
}

13.10.2 B. Patient Disposition Flow

Code
# Create CONSORT flow diagram using ggplot2
library(ggplot2)
library(grid)

# Create a simple CONSORT diagram
consort_plot <- ggplot(data = data.frame(x = 1:10, y = 1:10), aes(x, y)) +
  theme_void() +
  xlim(0, 10) + ylim(0, 10) +
  
  # Enrollment
  annotate("rect", xmin = 3, xmax = 7, ymin = 8.5, ymax = 9.5, fill = "lightblue", alpha = 0.5) +
  annotate("text", x = 5, y = 9, label = "Assessed for eligibility\n(n = 550)", size = 4) +
  
  # Exclusion
  annotate("segment", x = 5, xend = 5, y = 8.5, yend = 7.5, arrow = arrow(length = unit(0.2, "cm"))) +
  annotate("rect", xmin = 6, xmax = 9, ymin = 7, ymax = 8, fill = "pink", alpha = 0.5) +
  annotate("text", x = 7.5, y = 7.5, label = "Excluded (n = 41)\n• Not meeting criteria (n = 35)\n• Declined (n = 6)", size = 3) +
  
  # Randomization
  annotate("rect", xmin = 3, xmax = 7, ymin = 6.5, ymax = 7.5, fill = "lightgreen", alpha = 0.5) +
  annotate("text", x = 5, y = 7, label = "Randomized\n(n = 509)", size = 4) +
  
  # Allocation
  annotate("segment", x = 5, xend = 2.5, y = 6.5, yend = 5.5, arrow = arrow(length = unit(0.2, "cm"))) +
  annotate("segment", x = 5, xend = 7.5, y = 6.5, yend = 5.5, arrow = arrow(length = unit(0.2, "cm"))) +
  
  # Ven+Aza arm
  annotate("rect", xmin = 1, xmax = 4, ymin = 4.5, ymax = 5.5, fill = "#E41A1C", alpha = 0.3) +
  annotate("text", x = 2.5, y = 5, label = "Allocated to Ven+Aza\n(n = 256)", size = 4) +
  
  # Pbo+Aza arm
  annotate("rect", xmin = 6, xmax = 9, ymin = 4.5, ymax = 5.5, fill = "#377EB8", alpha = 0.3) +
  annotate("text", x = 7.5, y = 5, label = "Allocated to Pbo+Aza\n(n = 253)", size = 4) +
  
  # Follow-up
  annotate("segment", x = 2.5, xend = 2.5, y = 4.5, yend = 3.5, arrow = arrow(length = unit(0.2, "cm"))) +
  annotate("segment", x = 7.5, xend = 7.5, y = 4.5, yend = 3.5, arrow = arrow(length = unit(0.2, "cm"))) +
  
  # Analysis
  annotate("rect", xmin = 1, xmax = 4, ymin = 2.5, ymax = 3.5, fill = "#E41A1C", alpha = 0.3) +
  annotate("text", x = 2.5, y = 3, label = "Analyzed (n = 256)\nDeaths: 167 (65.2%)", size = 3.5) +
  
  annotate("rect", xmin = 6, xmax = 9, ymin = 2.5, ymax = 3.5, fill = "#377EB8", alpha = 0.3) +
  annotate("text", x = 7.5, y = 3, label = "Analyzed (n = 253)\nDeaths: 169 (66.8%)", size = 3.5) +
  
  labs(title = "VERONA Study CONSORT Flow Diagram") +
  theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5))

print(consort_plot)

13.10.3 C. Session Information

Code
# Display session information for reproducibility
sessionInfo()
R version 4.6.1 (2026-06-24)
Platform: aarch64-apple-darwin23
Running under: macOS Tahoe 26.6

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Chicago
tzcode source: internal

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
 [1] ggsci_5.2.0      patchwork_1.3.2  scales_1.4.0     gridExtra_2.3.1 
 [5] survminer_0.5.2  ggpubr_1.0.0     survival_3.8-6   kableExtra_1.4.1
 [9] knitr_1.51       lubridate_1.9.5  forcats_1.0.1    stringr_1.6.0   
[13] dplyr_1.2.1      purrr_1.2.2      readr_2.2.0      tidyr_1.3.2     
[17] tibble_3.3.1     ggplot2_4.0.3    tidyverse_2.0.0 

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       xfun_0.60          htmlwidgets_1.6.4  rstatix_1.1.0     
 [5] lattice_0.22-9     tzdb_0.5.0         vctrs_0.7.3        tools_4.6.1       
 [9] generics_0.1.4     pkgconfig_2.0.3    Matrix_1.7-5       RColorBrewer_1.1-3
[13] S7_0.2.2           lifecycle_1.0.5    compiler_4.6.1     farver_2.1.2      
[17] textshaping_1.0.5  carData_3.0-6      htmltools_0.5.9    yaml_2.3.12       
[21] Formula_1.2-5      pillar_1.11.1      car_3.1-5          abind_1.4-8       
[25] tidyselect_1.2.1   digest_0.6.39      stringi_1.8.7      labeling_0.4.3    
[29] splines_4.6.1      fastmap_1.2.0      cli_3.6.6          magrittr_2.0.5    
[33] broom_1.0.13       withr_3.0.3        backports_1.5.1    timechange_0.4.0  
[37] rmarkdown_2.31     ggtext_0.1.2       otel_0.2.0         ggsignif_0.6.4    
[41] hms_1.1.4          evaluate_1.0.5     viridisLite_0.4.3  rlang_1.3.0       
[45] Rcpp_1.1.2         gridtext_0.1.6     glue_1.8.1         xml2_1.6.0        
[49] svglite_2.2.2      rstudioapi_0.19.0  jsonlite_2.0.0     R6_2.6.1          
[53] systemfonts_1.3.2 

This analysis was prepared using R version R version 4.6.1 (2026-06-24) and Quarto for reproducible clinical research reporting.

Study Registration: ClinicalTrials.gov Identifier NCT04401748

Data Cutoff: April 10, 2025 | Median Follow-up: 41.2 months ```

13.11 Why is not more therapy always better for patients with HR-MDS?

The answer lies in toxicities that either offset efficacy benefits or that delay administration of effective therapy.

14 Clinical trials in HR-MDS

14.1 AK117 (Akesabio)

  • Anti CD47 antibody

  • No RBC agglutination compared to magrolimab

  • No requirement of “priming” dose

  • Lower incidence of anemia

  • Randomized phase 2 study (acrrual completed)

14.2 ASTX030 (oral AZA plus cedazuridine)

  • Phase 3

14.3 Bexirilimab study

  • FARON therapeutics
  • Clever-1 (common lymphatic endothelial and vascular endothelial receptor-1) constitutes a novel macrophage checkpoint. The receptor contributes to immune tolerance by antigen clearing and T cell inhibition
  • A first-in-class, humanized monoclonal antibody,bexmarilimab binds to Clever-1, an immunosuppressive receptor found on macrophages leading to tumor growth and metastases (i.e., it helps cancer to evade the immune system), and a novel immune checkpoint target for drug development.

14.3.1 Bexmarilimab plus Aza VS AZA for Frontline High-risk MDS

  • Anti-Clever-1
  • BEXMAB study
  • EHA 2025 abstract

15 IDH-mutant MDS

  • IDH MDS clinical phenotype: Neutropenia
  • IDH-mutant myeloid neoplasms and AIRD (Seronegtaive RA)(Hong et al. 2024)
  • LR-MDS progression to AML

15.1 Ivosidenib (IDH1i)

  • n=18
  • CR rate 38.9%
  • median OS 27.1 months

15.1.1 IDIOME trial

  • GFM study
  • Cohort A: HR-MDS HMA failure
  • Cohort B: HR-MDS HMA naive

15.2 Olutasidenib (IDH1i)

  • It can be active in post HMA/VEN

15.3 Enasidenib (IDH2i)

15.3.1 IDEAL study

15.4 AZA plus Luspatercept vs AZA monotherapy in HR-MDS

  • Study in China
  • First line
  • N=~86

  1. Venetoclax dose was reduced in more than half of the study patients and interrupted in ∼90% during the course of therapy, with 94% of patients experiencing grade 3 or 4 treatment-emergent adverse events.↩︎